/**
 * MeterialBottonView.java包描述<br>
 * 描述区
 *
 * @author haodai<br>
 * date: 18/5/25
 */
package com.zzh.views.bottom_module;

import android.content.Context;
import android.support.annotation.IdRes;
import android.support.design.widget.FloatingActionButton;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.Animation;
import android.view.animation.AnticipateInterpolator;
import android.view.animation.BounceInterpolator;
import android.view.animation.Interpolator;
import android.view.animation.TranslateAnimation;
import android.widget.FrameLayout;
import android.widget.Toast;

import com.zzh.views.R;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by haodai on 18/5/25.
 */
public class MeterialBottonView extends FrameLayout implements View.OnClickListener {
    private static final String TAG = MeterialBottonView.class.getSimpleName();

    private static final int LIFE_STATUS = 1;
    private static final int RIGHT_STATUS = 2;

    private Context mContext;

    private FloatingActionButton tabs;

    private FloatingActionButton itemOne;
    private FloatingActionButton itemTwo;
    private FloatingActionButton itemThree;
    private FloatingActionButton itemFour;
    private List<FloatingActionButton> floatingActionButtons;

    private int positionStatus = RIGHT_STATUS;


    private int lifeCentreX;
    private int rightCenterX;

    private int heightCenterY;

    private int tabsRadius = 0;
    private int childRadius = 0;

    private int height;
    private int width;

    // 动画进行中 所有点击手势操作暂停
    private boolean tabsAnimation = false;
    // 菜单状态
    private boolean isOpen = false;
    //菜单扩散位置数据
    private float toPosition[] = new float[6];


    public MeterialBottonView(Context context) {
        this(context, null);
    }

    public MeterialBottonView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MeterialBottonView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        height = getMeasuredHeight();
        width = getMeasuredWidth();
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        if (tabsRadius == 0) {
            tabsRadius = tabs.getHeight() / 2;
            lifeCentreX = tabsRadius + tabsRadius * 2;
            rightCenterX = width - lifeCentreX;
            heightCenterY = height - lifeCentreX;
        }
        if (childRadius == 0) {
            childRadius = itemOne.getHeight() / 2;
        }
        if (tabsRadius != 0) {
            if (positionStatus == LIFE_STATUS) {
                tabs.layout(lifeCentreX - tabsRadius, heightCenterY - tabsRadius, lifeCentreX + tabsRadius, heightCenterY + tabsRadius);
                setChildPosition(lifeCentreX - childRadius, heightCenterY - childRadius, lifeCentreX + childRadius, heightCenterY + childRadius);
            } else if (positionStatus == RIGHT_STATUS) {
                tabs.layout(rightCenterX - tabsRadius, heightCenterY - tabsRadius, rightCenterX + tabsRadius, heightCenterY + tabsRadius);
                setChildPosition(rightCenterX - childRadius, heightCenterY - childRadius, rightCenterX + childRadius, heightCenterY + childRadius);
            } else {
                tabs.layout(lifeCentreX - tabsRadius, heightCenterY - tabsRadius, lifeCentreX + tabsRadius, heightCenterY + tabsRadius);
                setChildPosition(lifeCentreX - childRadius, heightCenterY - childRadius, lifeCentreX + childRadius, heightCenterY + childRadius);
            }
        }
    }

    private void setChildPosition(int left, int top, int right, int bottom) {
        for (int i = 0; i < floatingActionButtons.size(); i++) {
            floatingActionButtons.get(i).layout(left, top, right, bottom);
        }
    }


    private void init(Context context, AttributeSet attrs) {
        mContext = context;
        View view = initView(context);
        addView(view);
        setListener();
        initValue();
    }

    private void initValue() {
        toPosition = location(500F);
    }

    private float[] location(float radius) {
        float[] value = new float[6];
        value[0] = radius;
        value[5] = radius;
        value[1] = (float) (radius * Math.cos(Math.PI / 6));//x
        value[2] = (float) (radius * Math.sin(Math.PI / 6));//y
        value[3] = (float) (radius * Math.cos(Math.PI / 3));//x
        value[4] = (float) (radius * Math.sin(Math.PI / 3));//y
        return value;
    }


    private View initView(Context context) {
        View view = LayoutInflater.from(context).inflate(R.layout.meterial_botton_viwe, null);
        tabs = fintView(view, R.id.tabs);
        itemOne = fintView(view, R.id.item_one);
        itemTwo = fintView(view, R.id.item_two);
        itemThree = fintView(view, R.id.item_three);
        itemFour = fintView(view, R.id.item_four);
        floatingActionButtons = new ArrayList<>();
        floatingActionButtons.add(itemOne);
        floatingActionButtons.add(itemTwo);
        floatingActionButtons.add(itemThree);
        floatingActionButtons.add(itemFour);
        return view;
    }

    private void setListener() {
        tabs.setOnClickListener(this);
        itemOne.setOnClickListener(this);
        itemTwo.setOnClickListener(this);
        itemThree.setOnClickListener(this);
        itemFour.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        if (tabsAnimation) return;
        int rId = v.getId();
        String value = "";
        if (rId == R.id.tabs) {
            if (isOpen) {
                close();
            } else {
                open();
            }
        } else if (rId == R.id.item_one) {
            value = "one";
        } else if (rId == R.id.item_two) {
            value = "two";
        } else if (rId == R.id.item_three) {
            value = "three";
        } else if (rId == R.id.item_four) {
            value = "four";
        } else {
            value = "five";
        }
        if (!TextUtils.isEmpty(value))
            Toast.makeText(mContext, value, Toast.LENGTH_SHORT).show();
    }

    private void open() {
        boolean isAnTop = tabs.getTop() + tabsRadius > height / 2 ? false : true;
        boolean isAnLeft = tabs.getLeft() - tabsRadius > width / 2 ? false : true;
        float[] values = creatPositionXY(isAnTop, isAnLeft);
        Animation animationOne = creatOpenAnimation(itemOne, values[0], values[1], values[2], values[3]);
        Animation animationTwo = creatOpenAnimation(itemTwo, values[4], values[5], values[6], values[7]);
        Animation animationThree = creatOpenAnimation(itemThree, values[8], values[9], values[10], values[11]);
        Animation animationFour = creatOpenAnimation(itemFour, values[12], values[13], values[14], values[15]);

        itemOne.startAnimation(animationOne);
        itemTwo.startAnimation(animationTwo);
        itemThree.startAnimation(animationThree);
        itemFour.startAnimation(animationFour);
        isOpen = true;
    }

    private void close() {
        boolean isAnTop = tabs.getTop() + tabsRadius > height / 2 ? false : true;
        boolean isAnLeft = tabs.getLeft() - tabsRadius > width / 2 ? false : true;
        float[] values = creatPositionXY(isAnTop, isAnLeft);
        Animation animationOne = creatCloseAnimation(itemOne, -values[0], -values[1], -values[2], -values[3]);
        Animation animationTwo = creatCloseAnimation(itemTwo, -values[4], -values[5], -values[6], -values[7]);
        Animation animationThree = creatCloseAnimation(itemThree, -values[8], -values[9], -values[10], -values[11]);
        Animation animationFour = creatCloseAnimation(itemFour, -values[12], -values[13], -values[14], -values[15]);
        itemOne.startAnimation(animationOne);
        itemTwo.startAnimation(animationTwo);
        itemThree.startAnimation(animationThree);
        itemFour.startAnimation(animationFour);
        isOpen = false;
    }

    private Animation creatCloseAnimation(final FloatingActionButton view,
                                          float fromX, final float toX, float fromY, final float toY) {
        final int center[] = getTabsCenter();
        Animation animation = new TranslateAnimation(fromX, toX, fromY, toY);
        animation.setDuration(500);
        animation.setInterpolator(new AnticipateInterpolator());
        animation.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {
                tabsAnimation = true;
            }

            @Override
            public void onAnimationEnd(Animation animation) {
                view.clearAnimation();
                view.layout(center[0] - childRadius, center[1] - childRadius, center[0] + childRadius, center[1] + childRadius);
                tabsAnimation = false;
            }

            @Override
            public void onAnimationRepeat(Animation animation) {

            }
        });
        return animation;
    }

    private Animation creatOpenAnimation(final FloatingActionButton view,
                                         float fromX, final float toX, float fromY, final float toY) {
        final int originalX = view.getLeft();
        final int originalY = view.getTop();
        Animation animation = new TranslateAnimation(fromX, toX, fromY, toY);
        animation.setDuration(1000);
        animation.setInterpolator(new BounceInterpolator());
        animation.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {
                tabsAnimation = true;
            }

            @Override
            public void onAnimationEnd(Animation animation) {
                view.clearAnimation();
                int toIntX = (int) toX;
                int toIntY = (int) toY;
                view.layout(originalX + toIntX, originalY + toIntY, originalX + toIntX + childRadius * 2, originalY + toIntY + childRadius * 2);
                tabsAnimation = false;
            }

            @Override
            public void onAnimationRepeat(Animation animation) {

            }
        });
        return animation;
    }

    private float[] creatPositionXY(boolean isAnTop, boolean isAnLeft) {
        float[] values = new float[16];
        if (isAnTop && isAnLeft) {
            //三相系
            values[0] = 0;
            values[1] = toPosition[0];
            values[2] = 0;
            values[3] = 0;

            values[4] = 0;
            values[5] = toPosition[1];
            values[6] = 0;
            values[7] = toPosition[2];

            values[8] = 0;
            values[9] = toPosition[3];
            values[10] = 0;
            values[11] = toPosition[4];

            values[12] = 0;
            values[13] = 0;
            values[14] = 0;
            values[15] = toPosition[5];
        } else if (isAnTop && !isAnLeft) {
            //四相系

            values[0] = 0;
            values[1] = -toPosition[0];
            values[2] = 0;
            values[3] = 0;

            values[4] = 0;
            values[5] = -toPosition[1];
            values[6] = 0;
            values[7] = toPosition[2];

            values[8] = 0;
            values[9] = -toPosition[3];
            values[10] = 0;
            values[11] = toPosition[4];

            values[12] = 0;
            values[13] = 0;
            values[14] = 0;
            values[15] = toPosition[5];
        } else if (!isAnTop && isAnLeft) {
            //二相系

            values[0] = 0;
            values[1] = toPosition[0];
            values[2] = 0;
            values[3] = 0;

            values[4] = 0;
            values[5] = toPosition[1];
            values[6] = 0;
            values[7] = -toPosition[2];

            values[8] = 0;
            values[9] = toPosition[3];
            values[10] = 0;
            values[11] = -toPosition[4];

            values[12] = 0;
            values[13] = 0;
            values[14] = 0;
            values[15] = -toPosition[5];
        } else {
            //一相系

            values[0] = 0;
            values[1] = -toPosition[0];
            values[2] = 0;
            values[3] = 0;

            values[4] = 0;
            values[5] = -toPosition[1];
            values[6] = 0;
            values[7] = -toPosition[2];

            values[8] = 0;
            values[9] = -toPosition[3];
            values[10] = 0;
            values[11] = -toPosition[4];

            values[12] = 0;
            values[13] = 0;
            values[14] = 0;
            values[15] = -toPosition[5];
        }
        return values;
    }


    //获取中心位置
    private int[] getTabsCenter() {
        int center[] = new int[2];
        center[0] = tabs.getLeft() + tabsRadius;
        center[1] = tabs.getTop() + tabsRadius;
        return center;
    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (tabsAnimation || isOpen) return super.onTouchEvent(event);
        switch (event.getAction()) {
            case MotionEvent.ACTION_UP:
                place();
                break;
            case MotionEvent.ACTION_MOVE:
                float centerX;
                float centerY;
                float x = event.getX();
                float y = event.getY();
                if (x < lifeCentreX - tabsRadius) {
                    centerX = lifeCentreX;
                } else if (x > rightCenterX + tabsRadius) {
                    centerX = rightCenterX;
                } else {
                    centerX = x;
                }
                if (y < lifeCentreX - tabsRadius) {
                    centerY = lifeCentreX;
                } else if (y > heightCenterY + tabsRadius) {
                    centerY = heightCenterY;
                } else {
                    centerY = y;
                }
                int xEnd = (int) centerX;
                int yEnd = (int) centerY;
                tabs.layout(xEnd - tabsRadius, yEnd - tabsRadius, xEnd + tabsRadius, yEnd + tabsRadius);
                for (int i = 0; i < floatingActionButtons.size(); i++) {
                    floatingActionButtons.get(i).layout(xEnd - childRadius, yEnd - childRadius, xEnd + childRadius, yEnd + childRadius);
                }
                break;
            default:
                break;
        }
        return super.onTouchEvent(event);
    }

    //回到指定位置的处理
    private void place() {
        float endX = tabs.getX() + tabsRadius;
        float endY = tabs.getY() + tabsRadius;
        // 位置确定
        final float[] transValue = toDealWithPosition(endX, endY);

        TranslateAnimation translateAnimation = new TranslateAnimation(transValue[0], transValue[1], transValue[2], transValue[3]);
        translateAnimation.setDuration(300);// 一秒时间归位
        final Interpolator interpolator = new AccelerateDecelerateInterpolator();
        translateAnimation.setInterpolator(interpolator);
        translateAnimation.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {
                tabsAnimation = true;
            }

            @Override
            public void onAnimationEnd(Animation animation) {
                tabs.clearAnimation();

                tabs.layout(
                        (int) transValue[4] - tabsRadius,
                        (int) transValue[5] - tabsRadius,
                        (int) transValue[4] + tabsRadius,
                        (int) transValue[5] + tabsRadius);
                tabsAnimation = false;
            }

            @Override
            public void onAnimationRepeat(Animation animation) {
            }
        });
        for (int i = 0; i < floatingActionButtons.size(); i++) {
            View view = floatingActionButtons.get(i);
            pliceChild(transValue, view);
        }

        tabs.startAnimation(translateAnimation);
    }

    private void pliceChild(final float[] transValue, final View view) {
        TranslateAnimation translateAnimation = new TranslateAnimation(transValue[0], transValue[1], transValue[2], transValue[3]);
        translateAnimation.setDuration(300);// 一秒时间归位
        final Interpolator interpolator = new AccelerateDecelerateInterpolator();
        translateAnimation.setInterpolator(interpolator);
        translateAnimation.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {
            }

            @Override
            public void onAnimationEnd(Animation animation) {
                view.clearAnimation();
                view.layout(
                        (int) transValue[4] - childRadius,
                        (int) transValue[5] - childRadius,
                        (int) transValue[4] + childRadius,
                        (int) transValue[5] + childRadius);
            }

            @Override
            public void onAnimationRepeat(Animation animation) {
            }
        });
        view.startAnimation(translateAnimation);
    }

    private float[] toDealWithPosition(float endX, float endY) {
        float[] values = new float[6];
        values[0] = 0;
        values[2] = 0;
        if (endY > heightCenterY) {
            values[3] = heightCenterY - endY;
            values[5] = heightCenterY;
        } else if (endY < lifeCentreX) {
            values[3] = lifeCentreX - endY;
            values[5] = lifeCentreX;
        } else {
            values[3] = 0;
            values[5] = endY;
        }
        int midpoint = width / 2;
        if (endX <= midpoint) {
            values[1] = lifeCentreX - endX;
            values[4] = lifeCentreX;
        } else if (endX > midpoint) {
            values[1] = rightCenterX - endX;
            values[4] = rightCenterX;
        } else {
            values[1] = rightCenterX - endX;
            values[4] = rightCenterX;
        }
        return values;
    }


    float downX = 0;
    float downY = 0;

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                downX = event.getX();
                downY = event.getY();
                Log.i(TAG, ">>>onInterceptTouchEvent>>down>>>>>");
                break;
            case MotionEvent.ACTION_MOVE:
                if (Math.abs(downX - event.getX()) > 24 || Math.abs(downY - event.getY()) > 24) {
                    return true;
                } else {
                    return super.onInterceptTouchEvent(event);
                }
            case MotionEvent.ACTION_UP:
                Log.i(TAG, ">>>onInterceptTouchEvent>>up>>>>>");
                break;
            default:
                return super.onInterceptTouchEvent(event);
        }
        return super.onInterceptTouchEvent(event);
    }


    private <T extends View> T fintView(View view, @IdRes int rId) {
        return (T) view.findViewById(rId);
    }
}
